/**
 *Copyright (c) 2024 watereyes
 * safetymanagement is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.system.service.impl;


import com.koron.common.bean.DepartmentTreeBean;
import com.koron.common.bean.StaffBean;
import com.koron.common.domain.DataBean;
import com.koron.common.generator.DefaultIdGenerator;
import com.koron.common.web.Util;
import com.koron.system.domain.OnlineLog;
import com.koron.system.domain.OperationLog;
import com.koron.system.domain.SigninLog;
import com.koron.system.mapper.OnlineLogMapper;
import com.koron.system.mapper.OperationLogMapper;
import com.koron.system.mapper.SigninLogMapper;
import com.koron.system.service.api.LogService;
import com.koron.system.util.IpUtils;
import com.koron.system.util.LocationUtils;
import com.koron.system.util.ServletUtils;
import nl.bitwalker.useragentutils.UserAgent;
import org.koron.ebs.mybatis.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class LogServiceImpl implements LogService {
    private final static  Logger logger = LoggerFactory.getLogger(LogServiceImpl.class);

    @Autowired
    private Util util;

    private final String PREFIX = "operation_log";

    @Override
    public DataBean<OperationLog> fetchOperationLog(Integer businessManipulation, String operatorName,String orgName,String businessModule,
                                                    Date beginTime, Date endTime, Integer start, Integer rows) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("beginTime = {}, endTime = {}", beginTime, endTime);
        }
        try (SessionFactory factory = new SessionFactory()) {
            OperationLogMapper mapper = factory.getMapper(OperationLogMapper.class);
            if (beginTime != null && endTime != null) {
                String tableName = getTableName(beginTime);
                String nextTableName = getTableName(endTime);
                if (tableName.equals(nextTableName)) {
                    List<OperationLog> operationLogs = mapper.queryByCondition(tableName, businessManipulation, operatorName, beginTime, endTime, start, rows,orgName,businessModule);
                    Integer total = mapper.countByCondition(tableName, businessManipulation, operatorName, beginTime, endTime,orgName,businessModule);
                    return inflate(operationLogs, total, start, rows);
                } else {
                    List<OperationLog> operationLogs = mapper.combineByCondition(tableName, nextTableName, businessManipulation, operatorName, beginTime, endTime, start, rows,orgName,businessModule);
                    Integer total = mapper.countCombination(tableName, nextTableName, businessManipulation, operatorName, beginTime, endTime,orgName,businessModule);
                    return inflate(operationLogs, total, start, rows);
                }
            } else {
                String tableName = getTableName(beginTime);
                if (tableName == null) {
                    tableName = getTableName(endTime);
                }
                if (tableName == null) {
                    tableName = getTableName(new Date());
                }
                List<OperationLog> operationLogs = mapper.queryByCondition(tableName, businessManipulation, operatorName, beginTime, endTime, start, rows,orgName,businessModule);
                Integer total = mapper.countByCondition(tableName, businessManipulation, operatorName, beginTime, endTime,orgName,businessModule);
                return inflate(operationLogs, total, start, rows);
            }
        }
    }


    private DataBean<OperationLog> inflate(List<OperationLog> operationLogs, Integer total, Integer start, Integer rows) {
        DataBean<OperationLog> dataBean = new DataBean<>();
        dataBean.setList(operationLogs);
        dataBean.setPageSize(rows);
        dataBean.setTotalNumber(total);
        dataBean.setTotalPage(total > rows ? (total % rows == 0? total/rows : total/rows + 1) : 1);
        dataBean.setPageNo(start / rows + 1);
        return dataBean;
    }


    private String getTableName(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        StringBuilder sb = new StringBuilder(PREFIX);
        sb.append("_").append(year);
        return sb.toString();
//        if (month > 5) {
//            return sb.append("07").toString();
//        } else {
//            return sb.append("01").toString();
//        }
    }

    @Override
    public OperationLog fetchOneOperationLog(String id, Date operationTime) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("id = {}, operationTime = {}", id, operationTime);
        }
        try (SessionFactory factory = new SessionFactory()) {
            OperationLogMapper mapper = factory.getMapper(OperationLogMapper.class);
            String tableName = getTableName(operationTime);
            return mapper.queryOne(tableName, id);
        }
    }

    @Override
    public Boolean batchDeteleOperationLog(List<OperationLog> operationLogs) throws Exception {
        Integer count = 0;
        List<String> idList = operationLogs.stream().map(OperationLog::getId).collect(Collectors.toList());
        Set<String> nameSet = operationLogs.stream().map(operationLog -> getTableName(operationLog.getOperationTime())).collect(Collectors.toSet());
        try (SessionFactory factory = new SessionFactory()) {
            OperationLogMapper mapper = factory.getMapper(OperationLogMapper.class);
            for (String tableName : nameSet) {
                count += mapper.batchDetele(tableName, idList);
            }
        }
        return count <= operationLogs.size();
    }


    @Override
    public Boolean signinLog() throws Exception {
        final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
        String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
        String os = userAgent.getOperatingSystem().getName();
        String browser = userAgent.getBrowser().getName();
        // 获取当前的用户
        StaffBean currentUser = ServletUtils.getSigninUser();
        // 封装对象
        SigninLog signinLog = new SigninLog();
        signinLog.setDeptName(currentUser.getDepartmentname());
        signinLog.setId(DefaultIdGenerator.getInstance().generateLongId());
        signinLog.setBrowser(browser);
        signinLog.setOs(os);
        signinLog.setIpaddr(ip);
        signinLog.setSigninLocation(LocationUtils.getRealAddressByIP(ip));
        signinLog.setSigninTime(new Date());
        signinLog.setSigninName(currentUser.getName());
        signinLog.setStatus(0);
        signinLog.setMsg("登录成功");
        if(currentUser.getCode() != null && !currentUser.getCode().isEmpty()) {
            //查询该用户所处公司名称
            DepartmentTreeBean corp = (DepartmentTreeBean) util.corp(currentUser.getCode()).getData();
            signinLog.setOrgName(corp.getName());
        }
        try (SessionFactory factory = new SessionFactory()) {
            SigninLogMapper mapper = factory.getMapper(SigninLogMapper.class);
            return mapper.insert(signinLog) > 0;
        }
    }


    @Override
    public DataBean<SigninLog> fetchSigninLog(String signinName, String browser, Date beginTime, Date endTime, Integer start, Integer rows, String orgName, String deptName) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("beginTime = {}, endTime = {}", beginTime, endTime);
        }
        try (SessionFactory factory = new SessionFactory()) {
            SigninLogMapper mapper = factory.getMapper(SigninLogMapper.class);
            List<SigninLog> signinLogs = mapper.queryByCondition(signinName, browser, beginTime, endTime, start, rows,orgName,deptName);
            Integer total = mapper.countByCondition(signinName, browser, beginTime, endTime,orgName,deptName);
            DataBean<SigninLog> dataBean = new DataBean<>();
            dataBean.setList(signinLogs);
            dataBean.setPageSize(rows);
            dataBean.setTotalNumber(total);
            dataBean.setTotalPage(total > rows ? (total % rows == 0? total/rows : total/rows + 1) : 1);
            dataBean.setPageNo(start / rows + 1);
            return dataBean;
        }
    }


    @Override
    public SigninLog fetchOneSigninLog(String id) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("id = {}", id);
        }
        try (SessionFactory factory = new SessionFactory()) {
            SigninLogMapper mapper = factory.getMapper(SigninLogMapper.class);
            return mapper.queryOne(id);
        }
    }


    @Override
    public Boolean batchDeteleSigninLog(List<String> idList) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("idList = {}", idList);
        }
        if (idList == null || idList.isEmpty()) {
            return true;
        }
        try (SessionFactory factory = new SessionFactory()) {
            SigninLogMapper mapper = factory.getMapper(SigninLogMapper.class);
            return mapper.batchDetele(idList) <= idList.size();
        }
    }


    @Override
    public DataBean<OnlineLog> fetchOnlineLog(String loginName, String deptName, String browser, Integer status, Integer start, Integer rows) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("loginName = {}, deptName = {}, browser = {}", loginName, deptName, browser);
        }
        try (SessionFactory factory = new SessionFactory()) {
            OnlineLogMapper mapper = factory.getMapper(OnlineLogMapper.class);
            List<OnlineLog> signinLogs = mapper.queryByCondition(loginName, deptName, browser, status, start, rows);
            Integer total = mapper.countByCondition(loginName, deptName, browser, status);
            DataBean<OnlineLog> dataBean = new DataBean<>();
            dataBean.setList(signinLogs);
            dataBean.setPageSize(rows);
            dataBean.setTotalNumber(total);
            dataBean.setTotalPage(total > rows ? (total % rows == 0? total/rows : total/rows + 1) : 1);
            dataBean.setPageNo(start / rows + 1);
            return dataBean;
        }
    }


    @Override
    public OnlineLog fetchOneOnlineLog(String id) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("id = {}", id);
        }
        try (SessionFactory factory = new SessionFactory()) {
            OnlineLogMapper mapper = factory.getMapper(OnlineLogMapper.class);
            return mapper.queryOne(id);
        }
    }


    @Override
    public Boolean batchDeteleOnlineLog(List<String> idList) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("idList = {}", idList);
        }
        if (idList == null || idList.isEmpty()) {
            return true;
        }
        try (SessionFactory factory = new SessionFactory()) {
            OnlineLogMapper mapper = factory.getMapper(OnlineLogMapper.class);
            return mapper.batchDetele(idList) <= idList.size();
        }
    }



}
